package com.holiday.spring.proxy.dynamic;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * spring动态代理有两种
 *      1、JDK动态代理
 *          1、自定义类并实现InvocationHandler类
 *  *       2、创建方法：newProxyInstance，这个方法的作用是：将目标类与代理类绑定关系
 *  *           1、Proxy.newProxyInstance
     *  *          1、第一个参数是：目标类的加载器
     *  *          2、第二个参数是：目标类的实现接口
     *  *          3、第三个参数是：目标类实现的方法
 *  *       2、实现方法：invoke
     *  *      1、Object proxy：在代理的类
     *  *      2、Method method：代理类中的方法
     *  *      3、Object[] args：代理类中方法的参数
 *      2、Cglib动态代理
 *          1、自定义类，并实现MethodInterceptor中的intercept方法
 *
 *
 *  总结：
 *      1、动态代理与静态代理相比较，最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理，解耦和易维护
 *      2、两种动态代理的区别：
 *          1、JDK动态代理：要求目标对象实现一个接口，但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以用CGLib动态代理
 *          2、CGLib动态代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展
 *          3、JDK动态代理是自带的，CGlib需要引入第三方包CGLib动态代理基于继承来实现代理，所以无法对final类、private方法和static方法实现代理
 *      3、Spring AOP中的代理使用的默认策略：
 *          1、如果目标对象实现了接口，则默认采用JDK动态代理
 *          2、如果目标对象没有实现接口，则采用CgLib进行动态代理
 *          3、如果目标对象实现了接口，程序里面依旧可以指定使用CGlib动态代理
 */
public class CglibProxy implements MethodInterceptor {

    // 用于存储目标类
    private Object targetObject;

    // 绑定目标类与代理类的关系
    public  Object  newProxyInstance(Object targetObject){
        this.targetObject = targetObject;
        Enhancer enhancer = new Enhancer();
        // 设置代理类的父类（目标类）
        enhancer.setSuperclass(this.targetObject.getClass());
        // 设置回调函数
        enhancer.setCallback(this);
        // 创建子类，代理对象
        return  enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //  调用目标类的方法
        Object result =null;
        System.out.println("xxxxx");
        result=methodProxy.invokeSuper(o,objects);
        System.out.println("xxxxxxxx");
        return result;
    }
}
